<template>
  <div class="SetupTempPage">
    <h3>组合式API的概念：</h3>
    <h4 class="tips">组合式API 是 选项是API 在js函数中的延申，用来抽离状态逻辑</h4>
    <h3>setup方法的特性：</h3>
    <h4 class="tips">1.调用时间点：调用在data、computed、methods被解析之前</h4>
    <h4 class="tips">2.使用方法：接收 props 和 context: { attrs, emit, slots, expose}，返回的所有内容都暴露给组件的其余部分</h4>

    <h4 class="tempDemo">示例一：在setup方法中，使用 函数 + 组合式API，抽离组件中的状态逻辑</h4>
    <button @click="togglePosition">切换位置</button>
    <subComponent :position="position"></subComponent>

    <h4 class="tempDemo">示例二：在setup方法中，使用 Provide / Inject （区别于选项式API，自带响应式，父子都可以同步修改该数据（不设置readonly时））</h4>
    <div>provide组件中：</div>
    <button @click="updateLocation">修改地区名</button>
    <div>地区名：{{ locationName }}</div>
    <div>经纬度： {{ JSON.stringify(geolocation, null, 2) }}</div>
    <injectActiveComponent></injectActiveComponent>

    <h4 class="tempDemo">示例三：在setup方法中，ref模板引用，以及侦听模板引用的生命周期函数</h4>
    <div>
      <button @click="triUpdateButton">{{ refTriUpdate }}</button>
    </div>
    <button @click="editRoot1">修改下面内容</button>
    <div ref="root1">onMounted中，获取当前DOM</div>
    <button @click="editRoot2">修改下面内容</button>
    <div ref="root2">watchEffect中，获取当前DOM</div>
  </div>
</template>

<script setup lang="ts">
import subComponent from "./components/subComponent.vue";
import injectActiveComponent from "./components/injectActiveComponent.vue";
import { defineComponent, provide, reactive, ref, readonly, onMounted, onBeforeUpdate, onUpdated, watchEffect } from "vue";



  const position = ref("广州")
  const refTriUpdate = ref("触发update")


    const locationName = ref("粤西");
    const geolocation = reactive({
      longitude: "90",
      latitude: "135",
    });

    const updateLocation = () => {
      locationName.value = "岭南";
    };

    provide("locationName", readonly(locationName));
    // provide("locationName", locationName);
    provide("geolocation", geolocation);
    provide("updateLocation", updateLocation);

    const root1 = ref(null);
    const root2 = ref(null);

    // DOM渲染完成后，获取ref
    onMounted(() => {
      console.log("onMounted!---root1", root1.value.innerText);
    });

    // 可以在每次更新之前清除ref，更新之后会自动添加ref，这样也就完成了更新ref（动态的ref时，需要这样操作，固定ref的不需要）
    onBeforeUpdate(() => {
      root1.value = null;
      console.log("onBeforeUpdate!---root1", root1.value);
    });
    onUpdated(() => {
      console.log("onUpdated!---root1更新", root1.value);
      console.log("onUpdated!---root2不更新", root2.value);
      console.log("--固定的ref不需要更新一样可以获取最新的，如上root2--");
    });

    // 监听模板引用变化的函数（此示例中，ref只在挂载时，由null变为root1才触发）
    // DOM更新前/后，由第二参数flush决定
    watchEffect(
      () => {
        console.log("watchEffect!---root2", root2.value.innerText);
      },
      {
        flush: "post",
      }
    );

    const togglePosition = () => {
      position.value = position.value === "广州" ? "珠海" : "广州";
    }
    const triUpdateButton = () => {
      refTriUpdate.value = refTriUpdate.value === "触发update" ? "已经触发update" : "触发update";
    }
    const editRoot1 = () => {
      // 下面的2种方式不会出发更新
      root1.value.setAttribute("key", "haha");
      root1.value.innerText = "haha";
      console.log("root1.value---", root1.value);
    }
    const editRoot2 = () => {
      root2.value.setAttribute("key", "lobo");
      root2.value.innerText = "lobo";
      console.log("root2.value---", root2.value);
    }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
.SetupTempPage {
  text-align: left;
  margin-left: 160px;
  h3 {
    color: skyblue;
    margin: 40px 0 0;
  }
  .tips {
    color: $myRedColor;
  }
  .tempDemo {
    margin-top: 40px;
  }
}
</style>
